/******************************************************************************
* 文件名  ：adc.c
* 文件描述：
* 创建人  ：
* 日    期：
* 
* 硬件连接：
            PC0 -  CP电压采样           adc123_ch10
            PC1 -  NTC1温度采样         adc123_ch11
            PC2 -  NTC2温度采样         adc123_ch12
            PC3 -  短路保护电压采样     adc123_ch13            
******************************************************************************/
#include "main.h"
#include "DRV_Adc.h"
#include "FreeRTOS.h"
#include "Task.h"

u16 g_AdcRawValue[ADC_TRANSFORM_NUM][ADC_CHANNEL_NUM];//adc原始数据
SemaphoreHandle_t g_AdcSem;


/*******************************************************************************
* Function Name  : void adc_init(void)
* Description    : 硬件ADC初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void adc_init(void)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    ADC_InitTypeDef     ADC_InitStructure;
    DMA_InitTypeDef     DMA_InitStructure;
    NVIC_InitTypeDef    NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);	//使能PC端口时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,  ENABLE);	//使能ADC1时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,    ENABLE);   //使能DMA传输

    /* 端口初始化 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 |GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; 	
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    /* ADC1 初始化 */
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);
    
    ADC_DeInit(ADC1);
	ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode       = ENABLE;	                    //模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;	                    //模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;	        //ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel       = ADC_CHANNEL_NUM;	            //顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	    

    ADC_RegularChannelConfig(ADC1, ADC_Channel_10,  1, ADC_SampleTime_239Cycles5 );
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11,  2, ADC_SampleTime_239Cycles5 );
    ADC_RegularChannelConfig(ADC1, ADC_Channel_12,  3, ADC_SampleTime_239Cycles5 ); 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_13,  4, ADC_SampleTime_239Cycles5 );
    
    ADC_DMACmd(ADC1, ENABLE);                   //使能ADC1的DMA传输 
    ADC_Cmd(ADC1, ENABLE);	                    //使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	                //使能复位校准  	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束	
	ADC_StartCalibration(ADC1);	                //开启AD校准
	while(ADC_GetCalibrationStatus(ADC1)){};    //等待校准结束
    
    /* DMA 初始化*/
    DMA_DeInit(DMA1_Channel1);

	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)( &ADC1->DR );             //DMA外设基地址
	DMA_InitStructure.DMA_MemoryBaseAddr     = (u32)&g_AdcRawValue;                 //DMA内存基地址
	DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;               //数据传输方向，从外设ADC发送到内存读取
	DMA_InitStructure.DMA_BufferSize         = ADC_CHANNEL_NUM * ADC_TRANSFORM_NUM; //DMA通道的DMA缓存的大小
	DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;           //外设地址寄存器不变
	DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;                //内存地址寄存器递增
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;     //数据宽度为16位
	DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;         //数据宽度为16位
	DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;                   //循环工作模式
	DMA_InitStructure.DMA_Priority           = DMA_Priority_High;                   //DMA通道 x拥有高优先级 
	DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;                     //DMA通道x没有设置为内存到内存传输
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    DMA_Cmd(DMA1_Channel1, ENABLE);
    
    DMA_ClearITPendingBit( DMA1_IT_TC1); 
    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC,ENABLE );     
    NVIC_InitStructure.NVIC_IRQChannel                   = DMA1_Channel1_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure );
    
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //浣胯兘鎸囧畾鐨凙DC1鐨勮蒋浠惰浆鎹㈠惎鍔ㄥ姛鑳?
    g_AdcSem=xSemaphoreCreateBinary();
}

/*******************************************************************************
* Function Name  : 
* Description    : 
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void DMA1_Channel1_IRQHandler()
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    if( DMA_GetITStatus( DMA1_IT_TC1 )== SET )//DMA传输完成 
    {
        DMA_ClearITPendingBit( DMA1_IT_TC1);
        ADC_Cmd( ADC1, DISABLE );
        //xTaskNotifyFromISR(task_tbl[TASK_ID_ADC].handle , 1 , eIncrement , &xHigherPriorityTaskWoken );//发送消息给adc处理任务
        xSemaphoreGiveFromISR(g_AdcSem,&xHigherPriorityTaskWoken);
    }
}

static uint16_t AxtractData[ADC_CHANNEL_NUM][ADC_TRANSFORM_NUM] = {0};
static uint32_t Sum[ADC_CHANNEL_NUM] = {0};
static uint16_t adc_avg_data[ADC_CHANNEL_NUM]={0};
static uint16_t cp_voltage=0;


uint8_t cp_voltage_get(uint16_t val)
{
	uint8_t retval = 0;
    
	if(val < 55)
	{
		retval = 0;
	}
	else if(val <= 65)
	{
		retval = 6;
	}
	else if(val <= 95)
	{
		retval = 9;
	}
	else if(val <= 125)
	{
		retval = 12;
	}
	else
	{
		retval = 0;
	}

	return retval;
}


uint8_t cp_info_get(uint16_t *p_volt, uint16_t *p_duty, uint16_t *p_freq)
{
    *p_volt = cp_voltage_get(cp_voltage);
    *p_duty = 0;
    *p_freq = 0;
    
    return 1;
}

/*******************************************************************************
* Function Name  : ADC_DataProcess
* Description    : ADC鏁版嵁澶勭悊
* Input          : 
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t cp_voltage_calc(uint16_t *pdata, uint8_t len)
{
     uint8_t i,cp_num=0;
    uint16_t voltage=0;
    uint32_t cp_adc_sum=0;
    
    for(i=0; i<len; i++)
    {
        if(pdata[i]>30)
        {
            cp_num++;
            cp_adc_sum+=pdata[i];
        }
    }
    if(cp_num)
    {        
        voltage = (uint16_t)(((float)cp_adc_sum/cp_num * 0.00321f + 0.5f)*10);
    }
    else
    {
        voltage = 0;
    }
        
    return voltage;
}

/*******************************************************************************
* Function Name  : ADC_DataProcess
* Description    : ADC鏁版嵁澶勭悊
* Input          : 
* Output         : None
* Return         : None
*******************************************************************************/
void ADC_DataProcess(void)
{
    uint8_t  i,j;
    
    /* 鎻愬彇姣忎釜閫氶亾鐨勬暟鎹?*/
    for(i=0; i<ADC_TRANSFORM_NUM; i++)
    {
        for(j=0; j<ADC_CHANNEL_NUM; j++)
        {
            AxtractData[j][i] = g_AdcRawValue[i][j];
        } 
    }
    
    cp_voltage = cp_voltage_calc(&AxtractData[0][0], ADC_TRANSFORM_NUM);
    
    
    /* 璁＄畻骞冲潎鍊?*/
    for(i=0; i<ADC_CHANNEL_NUM; i++)
    {
        for(j=0; j<ADC_TRANSFORM_NUM; j++)
        {
            Sum[i] += AxtractData[i][j];
        }
        adc_avg_data[i] = Sum[i]/ADC_TRANSFORM_NUM;
        Sum[i] = 0;
    }
}

//VCP=VADC*3.3/4096*4*510/512.2  + 0.5(offset)
void ADC_LOOP(void)
{
    if( xSemaphoreTake( g_AdcSem , 10) )
    {
        ADC_DataProcess();
        ADC_Cmd( ADC1, ENABLE );
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    }
}

